﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Linq.Expressions;
using System.ComponentModel;

namespace Hyt.Core
{
    public class Guard
    {
        public class JudgeClass<T>
        {
            internal T validobj { get; set; }

            /// <summary>
            /// 是否已判断过
            /// </summary>
            bool judged = false;

            /// <summary>
            /// 是否已处理过
            /// </summary>
            bool actioned = false;

            /// <summary>
            /// 是否已elsed过
            /// </summary>
            bool elsed = false;

            /// <summary>
            /// 判断结果
            /// </summary>
            bool? judgeresult = null;

            public JudgeClass<T> PleaseInput<Object>(params Expression<Func<T, Object>>[] expression)
            {
                foreach (var exp in expression)
                {
                    var p = exp.Compile()(validobj);
                    System.Linq.Expressions.MemberExpression membetexpression = exp.Body as System.Linq.Expressions.MemberExpression;
                    if (membetexpression == null)
                    {
                        throw new Exception("表达式不是有效的MemberExpression");
                    }
                    string name= TypeDescriptor.GetProperties(validobj).Find(membetexpression.Member.Name, true).Description;
                    Check(p).IfIsNull().Throw("请填写" + name);
                }
                return this;
            }
            
            public JudgeClass<T> DontNull(string objname)
            {
                if (validobj == null)
                {
                    throw new Exception(String.Format("{0}不能为空", objname));
                }
                else if (typeof(T) == typeof(String) && string.IsNullOrWhiteSpace(validobj.ToString()))
                {
                    throw new Exception(String.Format("{0}不能为空", objname));
                }
                return this;
            }
            
            public JudgeClass<T> IfIsNull()
            {
                Reset();
                if (validobj == null)
                {
                    judgeresult = true;
                }
                else if (typeof(T) == typeof(String) && string.IsNullOrWhiteSpace(validobj.ToString()))
                {
                    judgeresult = true;
                }
                else
                {
                    judgeresult = false;
                }
                judged = true;
                return this;
            }

            public JudgeClass<T> Throw(string msg)
            {
                if (!judged)
                {
                    throw new Exception("调用Throw方法前必须先判断");
                }
                if (actioned)
                {
                    throw new Exception("重复执行Throw");
                }
                if (judgeresult != null && judgeresult.Value)
                {
                    throw new Exception(msg);
                }
                actioned = true;
                return this;
            }

            public JudgeClass<T> ThrowNoExisted(string objname)
            {
                return Throw(String.Format("{0}不存在", objname));
            }

            public JudgeClass<T> Else(Action<T> handler)
            {
                if (!judged)
                {
                    throw new Exception("调用Else方法前必须先判断");
                }
                if (elsed)
                {
                    throw new Exception("重复执行Else");
                }
                if (judgeresult != null && !judgeresult.Value)
                {
                    handler(validobj);
                }
                elsed = true;
                return this;
            }

            public JudgeClass<T> Reset()
            {
                judged = false;
                actioned = false;
                elsed = false;
                judgeresult = null;
                return this;
            }

        }

        private const string AgainstMessage = "Assertion evaluation failed with 'false'.";
        private const string ImplementsMessage = "Type '{0}' must implement type '{1}'.";
        private const string InheritsFromMessage = "Type '{0}' must inherit from type '{1}'.";
        private const string IsTypeOfMessage = "Type '{0}' must be of type '{1}'.";
        private const string IsEqualMessage = "Compared objects must be equal.";
        private const string IsPositiveMessage = "Argument '{0}' must be a positive value. Value: '{1}'.";
        private const string IsTrueMessage = "True expected for '{0}' but the condition was False.";
        private const string NotNegativeMessage = "Argument '{0}' cannot be a negative value. Value: '{1}'.";

        private Guard()
        {
        }

        public static JudgeClass<T> Check<T>(T value)
        {
            JudgeClass<T> helper = new JudgeClass<T>();
            helper.validobj = value;
            return helper;
        }

        public static void CheckArg(object arg, string name)
        {
            if (arg == null)
            {
                throw new Exception(String.Format("{0}参数不能为空",name));
            }
        }
        public static void DontNull(object arg, string name)
        {
            if (arg == null)
            {
                throw new Exception(String.Format("{0}不能为空", name));
            }
        }
        public static void MustExist(object arg, string name)
        {
            if (arg == null)
            {
                throw new Exception(String.Format("{0}不存在", name));
            }
        }

        public static void Throw(string exp)
        {
            throw new Exception(exp);
        }
    }
}
